package auctionServer;

import auctionServer.businessLogic.ItemManager;
import auctionServer.businessLogic.Peer;
import auctionServer.eventService.EventServerManager;
import auctionServer.io.IOManager;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.rmi.RemoteException;
import java.util.ArrayList;

import auctionServer.network.ConnectionHandler;

public class AuctionServer {

	private ServerSocket server;
	private ArrayList<ConnectionHandler> connections;
	private ArrayList<Peer> offlinePeers;
	private boolean workingFlag;
	private ItemManager itemManager;
	
	private Thread itemCheckerThread;
	private boolean error;
    private EventServerManager outServerWaiter;

    public AuctionServer(int portNumber) {
		error = false;
		try {
			server = new ServerSocket( portNumber );//open server port
		}
		catch( IOException e ) {
			IOManager.throwWarning("Wanted port \""+portNumber+"\" is in usage! Server will be terminated!" );
			error = true;
		}
		workingFlag = false;
		connections = new ArrayList<ConnectionHandler>();
		offlinePeers = new ArrayList<Peer>();
		
		IOManager.addNotify("Server Connection port has been created.");

        try {
            outServerWaiter = new EventServerManager();
        } catch (RemoteException e) {
            e.printStackTrace();
            outServerWaiter.realeseConnection();
            IOManager.throwWarning("Wanted ports of RMI server is busy");
            error = true;
        }

        if(error)
            return;

        itemCheckerThread = new Thread(itemManager = new ItemManager(this));
		itemCheckerThread.start();
	}

	public void startServing() {
		IOManager.addNotify("Server on listening !!!");
		workingFlag = true;
		while( workingFlag ){
			try {
				Socket socket = server.accept();//wait for peer connections
				IOManager.addNotify("---Connection from: "+socket.getInetAddress()+":"+socket.getPort());
				
				ConnectionHandler ch = new ConnectionHandler(this,socket);
				Thread t = new Thread(ch);
				t.start();//create thread for each peer connection
				connections.add(ch);
			} catch (SocketException e){
				IOManager.addNotify("Server socket closed"); // mainly caused by stopServing method
			} catch (IOException e) {
			}
		}
		IOManager.addNotify("Serving has been finished");
		
		for (ConnectionHandler ch : connections) {
			try {
				ch.terminate();
			} catch (Exception e) {
				IOManager.throwWarning("Problem occoured while one of client's thread stopped");
			}
		}
		IOManager.throwWarning("All peers connections have been closed");
	}
	
	public void stopServing() {
		workingFlag = false;
		try {
			server.close();
		} catch (IOException e) {
		}
		
		try {
			itemManager.stopChecking();
			itemCheckerThread.join();
		} catch (InterruptedException e) {
		}

        outServerWaiter.realeseConnection();
	}

	public void leaveClient(ConnectionHandler connectionHandler) {
		offlinePeers.add(connectionHandler.getPeer());
		connections.remove(connections.indexOf(connectionHandler));
	}

	public ItemManager getItemManager() {
		return itemManager;
	}

	public boolean isError() {
		return error;
	}

	public ArrayList<Peer> getOfflinePeers() {
		return offlinePeers;
	}
	
}
